package ua.org.extjsbuilder.parser.runtime;

import java.util.HashMap;
import java.util.Map;

import ua.org.extjsbuilder.parser.IScope;
import ua.org.extjsbuilder.parser.IToken;
import ua.org.extjsbuilder.parser.ITokenList;
import ua.org.extjsbuilder.parser.JSObject;
import ua.org.extjsbuilder.parser.JSParseException;
import ua.org.extjsbuilder.parser.runtime.builder.AbstractRuntimeBuilder;
import ua.org.extjsbuilder.parser.runtime.data.JSConstants;

public class GeneralScope extends AbstractRuntimeBuilder 
		implements IScope, ITokenList {
	private Map<String,JSObject> scope;
	protected IScope parent;
	protected IToken head;
	
	public GeneralScope(IScope parent,IToken token){
		super(token);
		this.scope = new HashMap<String, JSObject>();
		this.parent = parent;
	}

	protected GeneralScope(IScope parent,int line) {
		super(line);
		this.scope = new HashMap<String, JSObject>();
		this.parent = parent;
	}

	@Override
	protected UnparsedToken getStartToken() {
		return getStartToken(head);
	}

	protected UnparsedToken getStartToken(IToken head) {
		while(head instanceof CommentToken){
			if(head==null)return null;
			head = head.getNext();
		}
		if(head==null)return null;
		if(head instanceof UnparsedToken){
			return (UnparsedToken) head;
		}
		throw new JSParseException("Unexpected literal", head.getLine());
	}

	public void generateAlly(String name) {
		// TODO Auto-generated method stub
		
	}

	public String getAlly(String name) {
		// TODO Auto-generated method stub
		return null;
	}

	public void define(String name, JSObject value) {
		scope.put(name, value);
	}

	public JSObject get(String name) {
		if(scope.get(name)==null&&parent!=null){
			return parent.get(name);
		}
		JSObject result = scope.get(name);
		if(result==null){
			return JSConstants.UNDEFINED;
		}
		return result;
	}

	public IToken getHead() {
		return head;
	}
	
	public int getSize() {
		int size = 0;
		IToken h = head;
		while(h!=null){
			size++;
			h=h.getNext();
		}
		return size;
	}

	public int getLine() {
		return head.getLine();
	}

	public boolean isDefined(String name) {
		if(!isDefinedLocaly(name)&&parent!=null){
			return parent.isDefined(name);
		}
		return isDefinedLocaly(name);
	}

	public boolean isDefinedLocaly(String name) {
		return scope.get(name)!=null||scope.get(name)!=JSConstants.UNDEFINED;
	}
}
